import requests
from bs4 import BeautifulSoup
import os
import sys


header = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36"
}


def get_play_list(url=None,list_num=None):
    # 歌单入口
    url = 'https://music.163.com/discover/playlist'

    # request请求类库，直接获取的html源代码
    result = requests.get(url, headers=header)

    # 对获取的html源代码进行处理，beautifulSoup对源码的处理
    html = BeautifulSoup(result.text, 'html.parser')
    # 过滤元素，查找ul标签，class为f-cb，再去查找里面的所有a标签，返回的是一个列表
    playlists = html.find('ul', {'class', 'f-cb'}).find_all('a')
    # 处理歌单列表
    playlist_dict = {}
    for playlist in playlists:
        list_id = playlist.get('href')
        if '/playlist?id=' in list_id:
            list_id = list_id.strip('/playlist?id=')
            list_name = playlist.get('title').strip()
            playlist_dict[list_id] = list_name
        if len(playlist_dict) == list_num:  # 爬取多少个歌单
            break
    return playlist_dict


def get_songs(list_id, song_num):
    # 获取歌单URL地址
    url = 'https://music.163.com/playlist?id={}'.format(list_id)
    # request请求类库，直接获取的html源代码
    result = requests.get(url, headers=header)

    # 对获取的html源代码进行处理，beautifulSoup对源码的处理
    html = BeautifulSoup(result.text, 'html.parser')
    # 过滤元素，查找ul标签，class为f-hide，再去查找里面的所有a标签，返回的是一个数组
    musics = html.find('ul', {'class', 'f-hide'}).find_all('a')
    music_dict = {}
    # 每个榜单数量太大，这里默认下载5首歌曲
    for music in musics:
        # 获取a标签对应的href，并过滤掉前面的song?id=，只留下歌曲的id
        music_id = music.get('href')
        if '/song?id=' in music_id:
            music_id = music.get('href').strip('/song?id=')
            # 获取歌曲的名称
            music_name = music.text
            # 组装为一个字典
            music_dict[music_id] = music_name
        if len(music_dict) == song_num:
            break
    return music_dict


def download_songs(music_id, music_name):
    # 歌曲下载地址
    url = "http://music.163.com/song/media/outer/url?id={}".format(music_id)
    try:
        save_dir = 'cloud_music'
        path = save_dir + '/' + music_name + '.mp3'
        if not os.path.exists(save_dir):
            os.makedirs(save_dir)
        if not os.path.exists(path):
            r = requests.get(url, headers=header)
            r.raise_for_status()
            with open(path, 'wb') as f:
                f.write(r.content)
                print(music_name + '.mp3 下载完成')
        else:
            print(music_name + '.mp3 已经下载')
    except KeyboardInterrupt:
        exit()
    except:
        pass


def main():
    try:
        list_num = int(input('输入搜索的歌单数量: '))
        song_num = int(input('输入单个歌单下载音乐的数量: '))
        playlist_dict = get_play_list(list_num=list_num)
        for list_id in playlist_dict:
            print('歌单id: {} 歌单名称:{}'.format(list_id, playlist_dict[list_id]))
            music_dict = get_songs(list_id, song_num=song_num)
            for music_id in music_dict:
                print('==>歌曲id: {} 歌曲名称: {}'.format(music_id, music_dict[music_id]))
                download_songs(music_id, music_dict[music_id])
    except KeyboardInterrupt:
        exit()
    except Exception as e:
        print(str(e))


main()
